/*
 *  WaveFunction.cpp
 *  SoundController0002
 *
 *  Created by jiro on 10/11/20.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#include "WaveFunction.h"
#include "Constants.h"
#include "SoundController.h"
#include <sstream>

namespace sc {

	double WaveFunction::GetCycle() const
	{
		return cycle;
	}

	double WaveFunction::GetNormailzer() const
	{
		return normalizer;
	}

	bool WaveFunction::operator == ( const WaveFunction& rhs ) const
	{
		if ( type == rhs.type && 
			 GetCycle() == rhs.GetCycle() &&
			 definedRangeOfX == rhs.definedRangeOfX &&
			 normalizer == rhs.normalizer )
		{
			return true;
		}
		return false;
	}
	
	bool WaveFunction::operator != ( const WaveFunction& rhs ) const
	{
		return not( *this == rhs );
	}
	
	bool WaveFunction::operator < ( const WaveFunction& rhs ) const
	{
		if ( type != rhs.type ) {
			return type < rhs.type;
		}
		if ( cycle != rhs.cycle ) {
			return cycle < rhs.cycle;
		}
		if ( definedRangeOfX != rhs.definedRangeOfX ) {
			return definedRangeOfX < rhs.definedRangeOfX;
		}
		if ( normalizer != rhs.normalizer ) {
			return normalizer < rhs.normalizer;
		}
		return false;
	}
	
	WaveFunction::Type WaveFunction::GetType() const
	{
		return type;
	}
	
	double WaveFunction::GetMaxOfY() const 
	{
		double delta = 1.0 / Sampling_Rate_As_Double;
		double x = definedRangeOfX.start;
		double max = - std::numeric_limits< double >::max();
		for ( ; x < definedRangeOfX.end; x += delta ) {
			double y = (*this)( x );
			if ( y > max ) {
				max = y;
			}
		}
		return max;
	}
	
	double WaveFunction::GetSlopeOfX() const 
	{
		return slopeOfX;
	}

	double WaveFunction::GetInterceptOfX() const
	{
		return interceptOfX;
	}

	std::string WaveFunction::ToString() const
	{
		std::stringstream ss;
		ss << "WaveFunction:\n";
		ss << "\t" << "type: ";
		switch ( type ) { 
		case Type_XSineX:
			ss << "Type_XSineX";
			break;
		case Type_LogXSinX:
			ss << "Type_LogXSinX";
			break;
		case Type_SinXVariableCycle:
			ss << "Type_SinXVariableCycle";
			break;
		case Type_SinPowerOfX:
			ss << "Type_SinPowerOfX";
			break;
		}
		
		ss << ", cycle: " << cycle;
		ss << ", definedRangeOfX: " << definedRangeOfX.ToString();
		ss << ", normalizer: " << normalizer;
		ss << ", slopeOfX: " << slopeOfX;
		ss << ", interceptOfX: " << interceptOfX;
		
		return ss.str();
	}

	WaveFunction::WaveFunction( Type type, double cycle, double normalizer, double slopeOfX, double interceptOfX )
	  : type( type ),
		cycle( cycle ),
		definedRangeOfX(),
		normalizer( normalizer ),
		slopeOfX( slopeOfX ),
		interceptOfX( interceptOfX )
	{}

	WaveFunction::WaveFunction( Type type, double cycle, Range definedRangeOfX, double normalizer, double slopeOfX, double interceptOfX )
	  : type( type ),
		cycle( cycle ),
		definedRangeOfX( definedRangeOfX ),
		normalizer( normalizer ),
		slopeOfX( slopeOfX ),
		interceptOfX( interceptOfX )
	{}

	double WaveFunction::ModifyX( double x ) const
	{
		double modifiedX = x;
		if ( modifiedX > definedRangeOfX.end ) {
			int diviser = static_cast< int >( modifiedX / definedRangeOfX.end );
			modifiedX -= diviser * definedRangeOfX.end;
		}
		return modifiedX;
	}

	void WaveFunction::SetNormalizer()
	{
		double max = GetMaxOfY();
		if ( max == 0 ) { 
			std::cout << "y max: " << max << std::endl; 
		} else {
			normalizer = 1.0 / GetMaxOfY();
		}
	}


}